package com.example.demo.Controller.Opus;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.Entity.Opus_Comment.OpusComment;
import com.example.demo.Entity.Opus_Like.OpusLike;
import com.example.demo.Entity.Topic.Topic;
import com.example.demo.Entity.UserInfo.Userinfo;
import com.example.demo.ServiceImpl.Opus.OpusServiceImpl;
import com.example.demo.Entity.Opus.Opus;
import com.example.demo.ServiceImpl.Opus_Comment.OpusCommentServiceImpl;
import com.example.demo.ServiceImpl.Opus_Like.OpusLikeServiceImpl;
import com.example.demo.ServiceImpl.Topic.TopicServiceImpl;
import com.example.demo.ServiceImpl.UserInfo.UserinfoServiceImpl;
import com.example.demo.Utils.JWTUtils.JWTUtils;
import com.example.demo.Utils.RedisUtils.RedisUtil;
import com.example.demo.Utils.Result.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@CrossOrigin(origins = "*")
@RequestMapping("/opus")
@Tag(name = "OpusController", description = "OpusController 相关接口")
public class OpusController {

    @Resource
    private OpusServiceImpl opusService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private TopicServiceImpl topicService;

    @Resource
    private UserinfoServiceImpl userinfoService;

    @Resource
    private OpusLikeServiceImpl opusLikeService;

    @Resource
    private OpusCommentServiceImpl opusCommentService;

    @Resource
    private RedisUtil redisUtil;

    @PostMapping
    @Operation(summary = "保存或更新 Opus 信息", description = "根据传入的 Opus 对象保存或更新信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "保存或更新成功", content = @Content(schema = @Schema(implementation = Boolean.class)))
    })
    public Boolean save(@RequestBody Opus opus, HttpServletRequest request) {
// 保存或更新数据后，删除相关缓存
        redisTemplate.delete("opus:all");
        redisUtil.deleteKeysStartingWith("opus");
        if (opus.getAuthor() == null) {
            String token = request.getHeader("Authorization");
            Integer userId = Integer.parseInt(JWTUtils.getUserIDFromToken(token));
            opus.setAuthor(userId);
            opus.setCreateTime(new Date());
        }
        return opusService.saveOrUpdate(opus);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "根据 ID 删除 Opus 信息", description = "根据传入的 ID 删除对应的 Opus 信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "删除成功", content = @Content(schema = @Schema(implementation = Boolean.class)))
    })
    public Boolean delete(@PathVariable(value = "id") Integer id) {
// 删除数据后，删除相关缓存
        redisTemplate.delete("opus:all");
        redisTemplate.delete("opus:id:" + id);
        return opusService.removeById(id);
    }

    @GetMapping
    @Operation(summary = "获取所有 Opus 信息", description = "获取所有 Opus 的列表信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = R.class)))
    })
    public R findAll() {
        String key = "opus:all";
        @SuppressWarnings("unchecked")
        List<Opus> opusList = (List<Opus>) redisTemplate.opsForValue().get(key);
        if (opusList == null) {
            opusList = opusService.list();
            redisTemplate.opsForValue().set(key, opusList, 60, TimeUnit.MINUTES);
        }
        return R.ok().put("opusList", opusList);
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据 ID 获取 Opus 信息", description = "根据传入的 ID 获取对应的 Opus 信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = R.class)))
    })
    public R findOne(@PathVariable(value = "id") Integer id,HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        Integer userId = Integer.parseInt(JWTUtils.getUserIDFromToken(token));
        Opus opus = opusService.getById(id);
        LambdaQueryWrapper<Userinfo>userinfoQueryWrapper = new LambdaQueryWrapper<>();
        userinfoQueryWrapper.eq(Userinfo::getUserId, opus.getAuthor());
        Userinfo userinfo = userinfoService.getOne(userinfoQueryWrapper);
        Topic topic = topicService.getById(opus.getTopicId());
        LambdaQueryWrapper<OpusLike>opusLikeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        opusLikeLambdaQueryWrapper.eq(OpusLike::getOpusId, id);
        List<OpusLike> opusLikes = opusLikeService.list(opusLikeLambdaQueryWrapper);
        Integer likedId=null;
        boolean liked = false;
        for (OpusLike opusLike : opusLikes) {
            if (opusLike.getLikeUserId().equals(userId)) {
                liked = true;
                likedId = opusLike.getLikeId();
                break;
            }
        }
        LambdaQueryWrapper<OpusComment>opusCommentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        opusCommentLambdaQueryWrapper.eq(OpusComment::getOpusId, id);
        List<OpusComment> opusComments = opusCommentService.list(opusCommentLambdaQueryWrapper);
        List<Userinfo>Users = new ArrayList<>();
        for (OpusComment opusComment : opusComments) {
            LambdaQueryWrapper<Userinfo>userinfoQueryWrapper1 = new LambdaQueryWrapper<>();
            userinfoQueryWrapper1.eq(Userinfo::getUserId, opusComment.getCommentUserId());
            Userinfo userinfo1 = userinfoService.getOne(userinfoQueryWrapper1);
            Users.add(userinfo1);
        }
        return R.ok().put("opus", opus).put("topic", topic).put("userinfo", userinfo).put("opusLikes", opusLikes).put("opusComments", opusComments).put("Users", Users).put("liked", liked).put("likedId", likedId);
    }

    @GetMapping("/page")
    @Operation(summary = "分页获取 Opus 信息", description = "根据传入的页码和每页数量分页获取 Opus 信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = R.class)))
    })
    @Parameter(name = "pageNum", in = ParameterIn.QUERY, description = "页码", required = true)
    @Parameter(name = "pageSize", in = ParameterIn.QUERY, description = "每页数量", required = true)
    @Parameter(name = "keyword", in = ParameterIn.QUERY, description = "搜索关键字")
    public R findPage(@RequestParam(value = "pageNum") Integer pageNum,
                      @RequestParam(value = "pageSize") Integer pageSize,
                      @RequestParam(value = "keyword", required = false) String keyword) {
        String key = "opus:page:" + pageNum + ":" + pageSize + ":" + keyword;
        @SuppressWarnings("unchecked")
        Page<Opus> opusPage = (Page<Opus>) redisTemplate.opsForValue().get(key);
        if (opusPage == null) {
            LambdaQueryWrapper<Opus> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.orderByDesc(Opus::getCreateTime);
            if (keyword != null && !keyword.isEmpty()) {
                queryWrapper.like(Opus::getOpusTitle, keyword);
                LambdaQueryWrapper<Userinfo> userinfoQueryWrapper = Wrappers.lambdaQuery();
                userinfoQueryWrapper.like(Userinfo::getUserId, keyword);
                List<Userinfo> userinfoList = userinfoService.list(userinfoQueryWrapper);
                if (userinfoList != null && !userinfoList.isEmpty()) {
                    List<Integer> userIds = new ArrayList<>();
                    for (Userinfo userinfo : userinfoList) {
                        userIds.add(userinfo.getUserId());
                    }
                    queryWrapper.or().in(Opus::getAuthor, userIds);
                }
                LambdaQueryWrapper<Topic> topicQueryWrapper = Wrappers.lambdaQuery();
                topicQueryWrapper.like(Topic::getTopicName, keyword);
                List<Topic> topicList = topicService.list(topicQueryWrapper);
                if (topicList != null && !topicList.isEmpty()) {
                    List<Integer> topicIds = new ArrayList<>();
                    for (Topic topic : topicList) {
                        topicIds.add(topic.getTopicId());
                    }
                    queryWrapper.or().in(Opus::getTopicId, topicIds);
                }
            }
            opusPage = opusService.page(new Page<>(pageNum, pageSize), queryWrapper);
            redisTemplate.opsForValue().set(key, opusPage, 60, TimeUnit.MINUTES);
        }
        List<String> UserNames = new ArrayList<>();
        List<String> TopicNames = new ArrayList<>();
        for (Opus opus : opusPage.getRecords()) {
            LambdaQueryWrapper<Userinfo> userinfoQueryWrapper = Wrappers.lambdaQuery();
            userinfoQueryWrapper.eq(Userinfo::getUserId, opus.getAuthor());
            Userinfo userinfo = userinfoService.getOne(userinfoQueryWrapper);
            if (userinfo != null) {
                UserNames.add(userinfo.getNickname());
            } else {
                UserNames.add("未知");
            }
            Topic topic = topicService.getById(opus.getTopicId());
            if (topic != null) {
                TopicNames.add(topic.getTopicName());
            } else {
                TopicNames.add("未知");
            }
        }
        return R.ok().put("opusPage", opusPage).put("UserNames", UserNames).put("TopicNames", TopicNames);
    }
}